import MQTT from "mqtt";
import {myStorage} from "@/utils/localStorage/index.js";
import mqttConfig from "@/../public/static/config.js"
import {ElMessage} from 'element-plus'
import router from "@/router/index.js";
import {onMsg} from "./msg.js";
import {SCADA_MSG} from '@/utils/Menu/menu.js'
import {logInfo, logWarn, logError} from "@/utils/log.js";

const MQTTBase = mqttConfig
let globalClientId;
const onTesting = false;

export var myMqtt;
let onMsgCallback = [];
let mySpecialId;

let Mqtt = function () {
  let mqttClient = null;
  let timer = null;
  let globalSubTopic = "yg_scada_service_send_msg";
  let willMsg = {funCode: 0, webMsgType: SCADA_MSG.scada_client_online_msg, clientId: globalClientId};
  let pubOption = {qos: 0, retain: false};

  let options = {
    clientId: getGuid32(),
    username: MQTTBase ? MQTTBase.username : "",
    password: MQTTBase ? MQTTBase.password : "",
    keepalive: 30,
    resubscribe: true,
    //遗嘱信息
    will: {
      topic: "yg_scada_service_recv_msg",
      payload: JSON.stringify(willMsg),
      retain: false,
      qos: 0,
    },
  };

  mqttClient = MQTT.connect(MQTTBase.url ? MQTTBase.url : ElMessage({
    showClose: true,
    type: 'error',
    duration: 0,
    message: '请填写配置里面的URL'
  }), options);
  mqttClient.on("connect", () => {
    logInfo("mqtt服务器连接成功");
    mqttClient.subscribe(globalClientId, {qos: 0});
    mqttClient.subscribe(globalSubTopic, {qos: 0});
    mqttClient.subscribe(options.clientId + '', {qos: 0});
    let msg = {webMsgType: SCADA_MSG.scada_client_online_msg, funCode: 1};
    broadcastMsg(msg);
    mqttClient.on("message", (topic, data) => {
      const msg = JSON.parse(data.toString());
      if (msg["retCode"] == -1) {
        ElMessage.error(msg["retMsg"]);
        router.push('/Login');
      } else {
        onMsg(topic, msg);
        for (let i = 0; i < onMsgCallback.length; i++) {
          onMsgCallback[i](topic, msg);
        }
      }
    });

    timer = window.setInterval(() => {
      let msg = {webMsgType: SCADA_MSG.scada_client_online_msg, funCode: 2};
      if (isConnected()) {
        broadcastMsg(msg);
      }
    }, 30000);

  });

  mqttClient.on("reconnect", (error) => {
    logWarn("正在重连:", error);
  });

  mqttClient.on("close", () => {
    logError("mqtt收到close事件，连接断开了");
    window.clearInterval(timer);
    timer = null;
  });

  mqttClient.on("disconnect", (packet) => {
    logError("mqtt收到disconnect事件，连接断开了");
  });

  mqttClient.on("offline", () => {
    logInfo("offline...");
    mqttClient.removeAllListeners("message");
  });

  mqttClient.on("error", (error) => {
    logError("mqtt收到error:", error);
  });

  isConnected = () => {
    return mqttClient.connected == true;
  };

  publishMsg = function (sendMsg) {
    mySpecialId = getGuid32();
    sendMsg["specialId"] = mySpecialId;
    sendMsg["clientId"] = globalClientId;
    if (onTesting) {
      sendMsg["testing"] = true;
    }
    mqttClient.publish(
      "yg_scada_service_recv_notify",
      JSON.stringify(sendMsg),
      pubOption,
      (err, a) => {
        if (err) {
          logError(err);
        }
      }
    );
    return mySpecialId;
  };

  broadcastMsg = function (sendMsg) {
    sendMsg["clientId"] = globalClientId;
    if (onTesting) {
      sendMsg["testing"] = true;
    }

    mqttClient.publish(
      "yg_scada_service_recv_msg",
      JSON.stringify(sendMsg),
      pubOption,
      (err, a) => {
        if (err) {
          logError(err);
        }
      }
    );
  };
  close = function () {
    this.mqttClient.end();
  };
};

function getClientId() {
  logInfo("getClientId() ");
  globalClientId = myStorage.get("clientId");
  if (globalClientId == null || globalClientId.length == 0) {
    globalClientId = getGuid32();
    myStorage.set("clientId", globalClientId);
  }
  logInfo("clientId:", globalClientId);
}

function isConnected() {
  return myMqtt.isConnected;
}

function reqPageConfig() {
  const req = {webMsgType: 1022, funCode: 0};
  publishMsg(req);
}

export function getGuid32() {
  let rt_str = String.fromCharCode(65 + Math.floor(Math.random() * 26));
  for (let i = 0; i < 31; ++i) {
    const num = Math.floor(Math.random() * (26 + 26 + 10));
    let ch_str;
    if (num < 10) {
      ch_str = num.toString();
    } else if (num < 10 + 26) {
      ch_str = String.fromCharCode(65 + num - 10);
    } else {
      ch_str = String.fromCharCode(97 + num - 10 - 26);
    }
    rt_str += ch_str;
  }
  return rt_str;
}

export function setMessageCallback(callback) {
  onMsgCallback.push(callback);
}

export function removeMessageCallback(callback) {
  let size = onMsgCallback.length;
  for (let i = 0; i < size; i++) {
    if (callback == onMsgCallback[i]) {
      onMsgCallback.splice(i, 1);
      break;
    }
  }
}

export function initMqtt() {
  logInfo("initMqtt");
  getClientId();
  myMqtt = new Mqtt();
}

export function broadcastMsg(sendMsg) {
  myMqtt.broadcastMsg(sendMsg);
}

export function publishMsg(sendMsg) {
  return myMqtt.publishMsg(sendMsg);
}

export function checkSpecialId(msg) {
  if (mySpecialId == msg['specialId']) {
    return true;
  } else {
    return false;
  }
}
